package com.example.f1.conf;

import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonRedisSerializer;
import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.serializer.RedisSerializationContext;

//1 org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration自动配置类
//2 https://docs.spring.io/spring-data/redis/docs/current/reference/html/#redis:support:cache-abstraction
@EnableCaching
@Configuration
@EnableConfigurationProperties({RedisProperties.class,CacheProperties.class})
public class Cache {

    @Value("${spring.cache.redis.db}")
    private int db;

    @Bean
    public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer(RedisProperties redisProperties){
        return builder -> {
            var configuration = new RedisStandaloneConfiguration();
            configuration.setHostName(redisProperties.getHost());
            configuration.setPort(redisProperties.getPort());
            configuration.setDatabase(db);

            var redisConnectionFactory=new LettuceConnectionFactory(configuration);
            redisConnectionFactory.afterPropertiesSet();

            builder.cacheWriter(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory));
        };
    }

    @Bean
    RedisCacheConfiguration redisCacheConfiguration(CacheProperties cacheProperties){
        var redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
        //使用GenericJackson2JsonRedisSerializer或者GenericFastJsonRedisSerializer
        //否则反序列化时会报转型错误
        var fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
//        var fjc=new FastJsonConfig();
//        fjc.setFeatures();
//        fastJsonRedisSerializer.setFastJsonConfig(fjc);
        redisCacheConfiguration=redisCacheConfiguration.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(fastJsonRedisSerializer));

        var redisProperties = cacheProperties.getRedis();
        if (redisProperties.getTimeToLive() != null) {
            redisCacheConfiguration = redisCacheConfiguration.entryTtl(redisProperties.getTimeToLive());
        }
        if (redisProperties.getKeyPrefix() != null) {
            redisCacheConfiguration = redisCacheConfiguration.prefixCacheNameWith(redisProperties.getKeyPrefix());
        }
        if (!redisProperties.isCacheNullValues()) {
            redisCacheConfiguration = redisCacheConfiguration.disableCachingNullValues();
        }
        if (!redisProperties.isUseKeyPrefix()) {
            redisCacheConfiguration = redisCacheConfiguration.disableKeyPrefix();
        }
        return redisCacheConfiguration;
    }

    //不配置KeyGenerator
    //https://docs.spring.io/spring-framework/reference/integration/cache/annotations.html#cache-annotations-cacheable-default-key

}
